# -*- coding:utf-8 -*-
#  <pre>
# 	@Description 该类文件为获取PerfServletApp.ear项目中SERVER的性能指标并入库的操作
#  </pre>
#  @copyright www.timotai.net
#  @author 这家伙真懒
#  @date 2016-1-10

import re
import urllib2
import config
import multiprocessing as mulpro
import os
import inspect
import sys
import dbtools
import time

content = ''
countItem = []
appList=[]
appInfo=[]
servers={}
typeList=[]
dirPath=''
typeItemData = {}

class Monitor(object):

    '''
        __init__
        get_current_function_name
        getContent
        getDataXml
        reMatch
        dtest
        parase
        writeFile
        writeDb
    '''

    def __init__(self):
        pass

    def get_current_function_name(self):
        '''
            get_current_function_name(self):

            :return: 类名.方法名
        '''
        return inspect.stack()[1][3]

    def getContent(self,url):
        '''
            getContent(self,url):
              eg: url   http://127.0.0.1:9080/wasPerfTool/servlet/perfservlet?server=server1
            :param url: 获取内容的URL
            :return: 返回URL中的内容
        '''
        try:
            request = urllib2.Request(url,headers = config.headers)
            response = urllib2.urlopen(request)
            value = response.read()
	    self.content = value
	    #print '********************************************'
	    #print value
            if config.is_debug:
                print "%s.%s invoked   URL:%s XMLCONTENT:%s"%(self.__class__.__name__,self.get_current_function_name(),url,value)
            return value
        except:
            (ErrorType,ErrorValue,ErrorTB)=sys.exc_info()
            print "Error: Connect failed:%s,errno=%s,ErrorType=%s,ErrorTB=%s"%(url,ErrorValue,ErrorType,ErrorTB)

    def getDataXml(self,name):
        '''
            根据URL中获取的内容按关键字抽取
            :param name: 'JVM Runtime','Object Request Broker'
            :return:
        '''
	return self.reMatch(config.CONTENT_RE%name,self.content)


    def reMatch(self,reg,value):
        '''
            reMatch(self,reg,value):
            正则表达式使用说明
                1. .*? 是一个固定的搭配，.和*代表可以匹配任意无限多个字符，
                     加上？表示使用非贪婪模式进行匹配，也就是我们会尽可能短地做匹配，以后我们还会大量用到 .*? 的搭配
                2. (.*?)加了一个括号表示将匹配到的内容返回，一个(.*?)代表一个分组，
                     就是一个返回来的值，如果在这个正则表达式中我们匹配了4个分组，在后面的遍历item中，
                    item[0]就代表第一个(.*?)所指代的内容，item[1]就代表第二个(.*?)所指代的内容，以此类推
                <div.*?class="auther.*?<img.*?alt="(.*?)"/>
                     这是获取第一个发布人信息的正则表达式
                     1. <div.*?class="auther.*?<img    从<div class="author开始匹配，匹配<div 到<img的内容
                     2. <img.*?alt="  匹配<img 到alt=" 之间的内容
                     3. alt="(.*?)"/> 匹配alt=" 到 "/> 的内容，(.*?) 加了一个括号表示将匹配到的内容返回
                     4. .*? 最后一个表示匹配剩下的所有内容

                <div.*?class="auther.*?<a.*?</a>.*?<a.*?title="(.*?)">.*?
                     这是获取第二个发布人信息的正则表达式
                     1. <div.*?class="auther.*?<a   从<div class="author开始匹配，匹配<div 到第一个<a的内容
                     2. <a.*?</a>.*?<a 为什么要有两个 <a ,我们再来看代码的相应的部分
                     print content
                     m = re.compile(r'<h2>(.*?)</h2>.*?'+'<div.*?class="content">(.*?)<!.*?'+
                         '<span.*?class="stats-vote">.*?<i.*?>(.*?)</i>.*?'+
                         '<a.*?class="qiushi_comments".*?<i.*?>(.*?)</i>.*?',re.S)
                      m = re.compile(r'<Stat name="JVM Runtime".*?</Stat>',re.S)

            :param reg: 正则表达式
            :param value: 读取的内容
            :return:
        '''
        match = re.compile(reg,re.S)
	value = value.decode('utf-8').encode('GBK')
	items = re.findall(match,value)
        if config.is_debug:
            print "%s.%s invoked   reg:%s value:%s   items:%s"%(self.__class__.__name__,self.get_current_function_name(),reg,value,items)
        return items

    def dtest(self,reg,value):
	match = re.compile(reg,re.S)
        items = re.findall(match,value)
	if config.is_debug:
            print "%s.%s invoked   reg:%s value:%s   items:%s"%(self.__class__.__name__,self.get_current_function_name(),reg,value,items)
        return items    

    def parase(self,value,type):

        '''
            parase(self,value):
            获取该内容中的参数值
            <CountStatistic ID="2" count="16082" lastSampleTime="1450771975225" name="FreeMemory" startTime="1450770854235" unit="KILOBYTE"/>
            result : FreeMemory   16082
        :param value:
        :return:
        '''
	valueArray = value[0].split("\n")
	global  countItem
        for key in valueArray:
            itemsCount = self.dtest(config.COUNT_RE,key)
	    itemsValue = self.dtest(config.VALUE_RE,key)
            if len(itemsCount+itemsValue)>0:
                if len(itemsValue)>0:
                    itemsValue = sorted(itemsValue[0])
                if len(itemsCount)>0:
                    itemsCount = sorted(itemsCount[0])
                countItem.append(itemsCount+itemsValue)

        currentTime = time.strftime('%H:%M:%S', time.localtime())
        countItem.append([currentTime,'currentDate'])
        typeItemData[type] = countItem
        countItem = []




    def writeFile(self,dirPath,fileName,value):
        '''
            :param dirPath: 目录按IP
            :param fileName: 文件名按SERVER名
            :param value: 要写入到文件中的内容
            :return:
        '''


        fileAllPath = config.FILEPATH+dirPath+os.sep
        if config.is_debug:
            print "filePath: %s"%(fileAllPath)
        try:
            if not os.path.exists(fileAllPath):
                os.mkdir(fileAllPath)
            file = open(fileAllPath+fileName, 'a')
            if os.path.getsize(fileAllPath+fileName)==0:
                for data in value:
                    file.write(str('#'+data[1])+'\t')
                file.write('\r\n')
            for data in value:
                file.write(str(data[0])+'\t\t\t')

            file.write('\r\n')
            file.close()
        except:
            (ErrorType,ErrorValue,ErrorTB)=sys.exc_info()
            print "Error: Connect failed:%s,errno=%s,ErrorType=%s,ErrorTB=%s"%(fileAllPath+fileName,ErrorValue,ErrorType,ErrorTB)


    def handle(self,servers):
        '''
            handle(self,servers):
                入口
            :param servers: config文件名SERVER的配置
            :return:
        '''
        for url in servers:
            self.getContent(url)
	    serverName = url[url.index('=')+1:]
            dataItem = self.reMatch(config.HTTP_RE,url)
            dirPath = dataItem[0][0]
            fileName = dataItem[0][1]

            typeList = getattr(config,'monitor_data')
            for type in typeList:
                value = self.getDataXml(type)
		self.parase(value,type)

            if config.is_debug:
                print "%s.%s invoked   dirPath:%s fileName:%s   items:%s"%(self.__class__.__name__,self.get_current_function_name(),dirPath,fileName,sorted(countItem))

            #开始写入文件
            #self.writeFile(dirPath,fileName,sorted(countItem))
            self.writeDb(typeItemData,serverName)


    def writeDb(self,typeItemData,serverName):
        '''
            writeDb(self,typeItemData,serverName):
                typeItemData   解析出来的性能数据
                serverName     SERVER名称
        '''
	sqlend,sqlbegin ='(','('

	# 初始化数据源
        dbtools.init()

        # 获取CONNECTION
        conn = dbtools.get_conn(dbtools.DB_FILE_PATH)

        # 遍历数据性能指标
        for key in typeItemData:
            for item in typeItemData[key]:
		sqlend+="'"+item[0]+"',"
                sqlbegin+=item[1]+','

	    # 拼装SQL
  	    sqlend+="'"+serverName+"',"
	    sqlbegin+='serverName,'
            sqlend =sqlend[0:-1]+')'
            sqlbegin =sqlbegin[0:-1]+')'
            if key == config.monitor_data[0]:
                tableName = config.TABLE_NAME[0]
                createSql = config.CREATE_JVM_SQL.format(tableName,config.DBQUEUE)
                insetSql = config.INSERT_SQL.format(tableName,config.DBQUEUE) +sqlbegin + config.VALUES + sqlend
            	createIndex = config.CREATE_INDEX.format(tableName,config.DBQUEUE+'jvm',tableName,config.DBQUEUE)
	    else :
                tableName = config.TABLE_NAME[1]
                createSql = config.CREATE_THREAD_SQL.format(tableName,config.DBQUEUE)
                insetSql = config.INSERT_SQL.format(tableName,config.DBQUEUE) +sqlbegin + config.VALUES + sqlend
		createIndex = config.CREATE_INDEX.format(tableName,config.DBQUEUE+'thred',tableName,config.DBQUEUE)
            sqlend,sqlbegin ='(','('
            result = dbtools.is_table_exist(conn, config.IS_TABLE_EXIST.format(tableName,config.DBQUEUE))
            if result:
                dbtools.create_table(conn,createSql)
		dbtools.create_table(conn,createIndex)
            dbtools.save(conn,insetSql)

if __name__=='__main__':

    try:
        appList = getattr(config,"test_yyapp")
        for app in appList:
             servers = getattr(config,app)
        pool = mulpro.Pool(processes=16)
        monitor = Monitor()
        pool.apply_async(monitor.handle(servers))
        # monitor.handle(servers)
        pool.close()
        pool.join()

    except urllib2.URLError,e:
        if hasattr(e,'code'):
            print e.code
        if hasattr(e,'reason'):
            print e.reason


